// services/api.js 
import axios from 'axios';
import { message } from 'antd';
import store from '../store';
import { forceRelogin } from '../store/authSlice';
import debounce from 'lodash/debounce';
import { getRequestData, saveRequestData, resetRequestData } from './storageManager';

// 定义阈值、窗口期和冷却时间
const maxRequestCount = 10; // 最大请求次数的阈值
const windowInterval = 10000; // 窗口期（毫秒），8秒
const cooldownInterval = 12000; // 冷却时间（毫秒），10秒

// 初始化请求计数和时间戳
let { count: requestCount, timestamp: lastRequestTime } = getRequestData();
let isCooldown = false; // 冷却状态标志
let cooldownTimeoutId; // 用于存储冷却期的 timeout ID

// 启动冷却期
const startCooldown = () => {
  isCooldown = true; // 进入冷却状态
  lastRequestTime = Date.now(); // 更新时间戳

  cooldownTimeoutId = setTimeout(() => {
    isCooldown = false; // 冷却期结束，退出冷却状态
    requestCount = 0; // 冷却期结束后重置请求计数
    lastRequestTime = Date.now(); // 冷却期结束时重置时间戳为当前时间
    saveRequestData(requestCount, lastRequestTime); // 保存新的时间戳
  }, cooldownInterval);
};

// 检查并重置请求计数
const resetRequestCount = () => {
  const now = Date.now();
  if (!isCooldown && (now - lastRequestTime > windowInterval)) {
    requestCount = 0;
    lastRequestTime = now;
    resetRequestData(); // 使用 storageManager 重置数据
    clearTimeout(cooldownTimeoutId); // 清除冷却期的定时器（如果有）
  }
};

// 创建一个防抖函数生成器，用于包装请求方法
const createDebouncedRequest = (apiInstance, delay = 300) => {
  const debouncedRequest = debounce((config, resolve, reject) => {
    resetRequestCount(); // 在防抖函数内部处理计数重置

    if (isCooldown) {
      const remainingTime = cooldownInterval - (Date.now() - lastRequestTime);
      const remainingSeconds = Math.ceil(remainingTime / 1000);
      if (config.handleErrorInternally !== false) {
        message.warning(`请求过于频繁，请在 ${remainingSeconds} 秒后重试。`);
      }
      reject({ message: `请求过于频繁，请在 ${remainingSeconds} 秒后重试。` });
      return;
    }

    requestCount++;
    saveRequestData(requestCount, Date.now()); // 使用 storageManager 保存数据

    if (requestCount > maxRequestCount) {
      startCooldown(); // 启动冷却期
      if (config.handleErrorInternally !== false) {
        message.error(`请求过于频繁，请在 ${cooldownInterval / 1000} 秒后重试。`);
      }
      reject({ message:`请求过于频繁，请在 ${cooldownInterval / 1000} 秒后重试。`});
      return;
    }

    // 执行请求
    apiInstance(config)
      .then(resolve)
      .catch(reject);
  }, delay);

  return (config) => new Promise((resolve, reject) => {
    debouncedRequest(config, resolve, reject);
  });
};

// 获取环境变量中的基础 URL
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || '/api';

console.log('API_BASE_URL:', API_BASE_URL); // 打印基础 URL 以便调试.

// 创建需要 JWT 认证的 Axios 实例
const api = axios.create({
  baseURL: API_BASE_URL, // 直接使用云服务器地址
});

// 请求拦截器：在请求头中添加 JWT token
api.interceptors.request.use(
  config => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => Promise.reject(error)
);

// 响应拦截器：统一处理后端返回的 HTTP 状态码
api.interceptors.response.use(
  response => response,
  error => {
    const { response, config } = error;
    const handleError = config.handleErrorInternally !== false; // 是否需要内部错误处理

    if (response) {
      const { status, data } = response;

      // 针对不同的状态码进行处理
      switch (status) {
        case 400:
          if (handleError) message.error(data.message || '请求错误');
          return Promise.reject({ handled: true, status, message: data.message || '请求错误' });

        case 401:
          if (handleError) handleUnauthorized();
          return Promise.reject({ handled: true, status, message: '未授权，请重新登录' });

        case 403:
          if (handleError) message.error('您没有此资源的操作权限');
          return Promise.reject({ handled: true, status, message: '没有操作权限' });

        case 404:
          if (handleError) message.error('请求的资源未找到');
          return Promise.reject({ handled: true, status, message: '资源未找到' });

        case 500:
          if (handleError) message.error('服务器内部错误');
          return Promise.reject({ handled: true, status, message: '服务器内部错误' });

        case 429:
          if (handleError) message.error(data.message || '请求过于频繁，请稍后尝试');
          return Promise.reject({ handled: true, status, message: data.message || '请求过于频繁，请稍后重试' });

        default:
          if (handleError) message.error(`未知错误 (${status})`);
          return Promise.reject({ handled: true, status, message: `未知错误 (${status})` });
      }
    } else {
      if (handleError) {
        message.error('网络错误，请稍后重试');
      }
      return Promise.reject({ handled: false, status: null, message: '网络错误，请稍后重试' });
    }
  }
);


// 处理 401 错误（未授权）
const handleUnauthorized = () => {
  store.dispatch(forceRelogin());
};

// 创建不需要 JWT 认证的 Axios 实例
const anonymousApi = axios.create({
  baseURL: API_BASE_URL, // 与 `api` 实例相同的基础 URL
});

// 响应拦截器：处理匿名 API 的错误
anonymousApi.interceptors.response.use(
  response => response,
  error => {
    const { response, config } = error;
    const handleError = config.handleErrorInternally !== false; // 是否需要内部错误处理

    if (response) {
      const { status, data } = response;

      switch (status) {
        case 400:
          if (handleError) message.error(data.message || '请求错误');
          return Promise.reject({ handled: true, status, message: data.message || '请求错误' });

        case 404:
          if (handleError) message.error('请求的资源未找到');
          return Promise.reject({ handled: true, status, message: '资源未找到' });

        case 500:
          if (handleError) message.error('服务器内部错误');
          return Promise.reject({ handled: true, status, message: '服务器内部错误' });

        case 429:
          if (handleError) message.error(data.message || '请求过于频繁，请稍后尝试');
          return Promise.reject({ handled: true, status, message: data.message || '请求过于频繁，请稍后重试' });

        default:
          return Promise.reject({ handled: false, status, message: `错误 (${status})` });
      }
    } else {
      if (handleError) {
        message.error('网络错误，请稍后重试');
      }
      return Promise.reject({ handled: false, status: null, message: '网络错误，请稍后重试' });
    }
  }
);

// 为 `api` 和 `anonymousApi` 添加防抖机制
api.debouncedRequest = createDebouncedRequest(api);
anonymousApi.debouncedRequest = createDebouncedRequest(anonymousApi);

// 导出 `api` 和 `anonymousApi`
export { api, anonymousApi };
